<template>
  <div style="margin-left: 15px;border-bottom:1px solid #E5EBEE;width:97%;border-top:1px solid #E5EBEE;">
    <el-checkbox size="large" v-model="options.quoteKeys" @change="doFormat(content)">引号</el-checkbox>
    <el-checkbox v-model="options.isCollapsible" @change="doFormat(content)" style="margin-left:-15px;" size="large">
      自己折叠</el-checkbox>
    &nbsp; &nbsp;
    <el-button type="text" @click="collapseAll">折叠</el-button>
    <el-button type="text" @click="collapseLevel">展开</el-button>
    <span style="color:#E5EBEE"> &nbsp;|&nbsp;</span>
    <el-button type="text" @click="Compress()">压缩</el-button>
    <el-button type="text" @click="Vary()">转义</el-button>
    <el-button type="text" @click="RemoveVary()">去转义</el-button>
    <el-button type="text" @click="GenerateEntity">生成实体</el-button>
    <span style="color:#E5EBEE"> &nbsp;|&nbsp;</span>
    <el-button type="text" @click="SelectAllClicked()">复制<i class="el-icon-tickets el-icon--right"></i></el-button>
    <span style="font-size:12px;color:#AAAA;float:right;margin-top:13px">击可进行编辑</span>
  </div>
  <div id="Canvas" class="Canvas" style="overflow-y:auto;height:92%;"></div>



  <el-drawer v-model="dialog" title="c#实体" @opened="open">
    <template #default>
      <div id="ec_div" style="height:99%;overflow:auto"></div>
    </template>
  </el-drawer>

</template>

<script>
  import { ref, reactive, onUnmounted } from 'vue';
  import collapsedUrl from '@/assets/jsonFormater/images/Collapsed.gif';
  import expandedUrl from '@/assets/jsonFormater/images/Expanded.gif';
  export default {

    setup() {

      const content = ref();
      const dialog = ref(false);
      const showSummary = ref(false);
      const changeContent = (value) => {
        content.value = value;
      }
      const options = reactive({
        dom: "",
        tabSize: 2,
        singleTab: "  ",
        quoteKeys: true,
        imgCollapsed: collapsedUrl,
        imgExpanded: expandedUrl,
        isCollapsible: true,
        allClass: []
      });
      let isFormated = false;
      const obj = {
        _dateObj: new Date(),
        _regexpObj: new RegExp()
      }

      const multiplyString = (num, str) => {
        var result = '';
        for (var i = 0; i < num; i++) {
          result += str;
        }
        return result;
      };
      //是否是数组
      const isArrayCheck = (obj) => {
        return obj &&
          typeof obj === 'object' &&
          typeof obj.length === 'number' && !(obj.propertyIsEnumerable('length'));
      };

      const tab = multiplyString(options.tabSize, options.singleTab);


      //压缩
      const Compress = () => {
        options.isCollapsible = false;
        var html;
        var obj = eval("[" + content.value + "]");
        html = ProcessObject(obj[0], 0, false, false, false);
        SetresultJson(html);
      };
      //转义
      const Vary = () => {
        try {
          options.isCollapsible = false;
          let html;
          var obj = eval("[" + content.value + "]");
          html = ProcessObject(obj[0], 0, false, false, false);
          html = html.replace(/"/g, '\\"');
          SetresultJson(html);
        } catch (e) {
          document.getElementById('Canvas').innerHTML = "<pre  style='font-size:15px;color:#F3592A' >" + e + "</span>";
        }
      };
      //去转义
      const RemoveVary = () => {
        try {
          let html;
          options.isCollapsible = false;
          var jsonStr = content.value.replace(/\\/g, '');
          doFormat(jsonStr);
        } catch (e) {
          document.getElementById('Canvas').innerHTML = "<pre  style='font-size:15px;color:#F3592A' >" + e + "</span>";
        }
      };

      //复制
      const SelectAllClicked = () => {

        // debugger
        if (!!document.selection && !!document.selection.empty) {

          document.selection.empty();

        } else if (window.getSelection) {

          var sel = window.getSelection();

          if (sel.removeAllRanges) {

            window.getSelection().removeAllRanges();
          }

        }
        var range = (!!document.body && !!document.body.createTextRange) ? document.body.createTextRange() : document.createRange();

        if (!!range.selectNode) {
          range.selectNode(document.getElementById('Canvas'));
        }
        else if (range.moveToElementText) {
          range.moveToElementText(document.getElementById('Canvas'));
        }


        if (!!range.select) {
          range.select(document.getElementById('Canvas'));
        } else {
          window.getSelection().addRange(range);
        }
        document.execCommand("Copy"); 
      };

      //生成实体 打开窗口
      const GenerateEntity = () => {
        dialog.value = true;
      };
      //生成实体
      const open = () => {
        if (content.value) {
          options.allClass = [];
          GetenClassCode(JSON.parse(content.value), 'Entity', showSummary);
          var html = "";
          var val = options.allClass;
          for (var i = (val.length - 1); i >= 0; i--) {
            html += val[i];
          }
          document.getElementById('ec_div').innerHTML = html;
        }
      }

      //外部调用入扣
      const RenderJosnHtml = (json) => {
        try {
          content.value = json;
          JSON.stringify(JSON.parse(json), null, 4);
          doFormat(json);
        } catch (e) {
          document.getElementById('Canvas').innerHTML = "<pre  style='font-size:15px;color:#F3592A' >" + e + "</span>";
        }
      }

      //开始格式化
      const doFormat = (json) => {

        if (!json)
          return;
        var html;
        var obj;
        try {
          if (typeof json == 'object') {
            obj = [json];
          } else {
            if (json == "") {
              json = "\"\"";
            }
            obj = eval("[" + json + "]");
          }
          html = ProcessObject(obj[0], 0, false, false, false);
          document.getElementById('Canvas').innerHTML = "<pre class='jf-CodeContainer'  >" + html + "</pre>";
          isFormated = true;
          bindEvent();
        } catch (e) {
          alert("JSON数据格式不正确:\n" + e.message);
          document.getElementById('Canvas').innerHTML = ''
          isFormated = false;
        }
      };

      //展开
      const extend = (out) => {
        out = out || {};
        for (var i = 1; i < arguments.length; i++) {
          if (!arguments[i])
            continue;
          for (var key in arguments[i]) {
            if (arguments[i].hasOwnProperty(key))
              out[key] = arguments[i][key];
          }
        }

        return out;
      };


      //绑定
      const bindEvent = () => {
        const that = this;
        var elements = document.getElementsByClassName('imgToggle');

        Array.prototype.forEach.call(elements, function (el, i) {
          el.addEventListener('click', function () {
            if (isFormated == false) {
              return;
            }
            makeContentVisible(this.parentNode.nextElementSibling, !parseInt(this.getAttribute('data-status')));
          });
        });
      };


      //全部展开
      const expandAll = () => {
        if (isFormated == false) {
          return;
        }
        var that = this;
        traverseChildren(options.dom, function (element) {
          if (element.classList.contains('jf-collapsible')) {
            makeContentVisible(element, true);
          }
        }, 0);
      };

      //全部关闭
      const collapseAll = () => {
        if (isFormated == false) {
          return;
        }
        var that = this;
        traverseChildren(document.getElementById('Canvas'), function (element) {
          if (element.classList.contains('jf-collapsible')) {
            makeContentVisible(element, false);
          }
        }, 0);
      };

      //层级关闭
      const collapseLevel = (level) => {
        if (isFormated == false) {
          return;
        }
        var that = this;
        traverseChildren(document.getElementById('Canvas'), function (element, depth) {
          if (element.classList.contains('jf-collapsible')) {
            if (depth >= level) {
              makeContentVisible(element, false);
            } else {
              makeContentVisible(element, true);
            }
          }
        }, 0);

      };


      //获取row
      const getRow = (indent, data, isPropertyContent) => {
        var tabs = "";
        if (!isPropertyContent) {
          tabs = multiplyString(indent, tab);
        }
        if (data != null && data.length > 0 && data.charAt(data.length - 1) != "\n") {
          data = data + "\n";
        }
        return tabs + data;
      };


      //格式化文字
      const formatLiteral = (literal, quote, comma, indent, isArray, style) => {
        if (typeof literal == 'string') {
          literal = literal.split("<").join("&lt;").split(">").join("&gt;");
        }
        var str = "<span class='jf-" + style + "' contenteditable='true' >" + quote + literal + quote + comma + "</span>";
        if (isArray) str = getRow(indent, str);
        return str;
      };


      //格式化函数
      const formatFunction = (indent, obj) => {
        var tabs;
        var i;
        var funcStrArray = obj.toString().split("\n");
        var str = "";
        tabs = multiplyString(indent, tab);
        for (i = 0; i < funcStrArray.length; i++) {
          str += ((i == 0) ? "" : tabs) + funcStrArray[i] + "\n";
        }
        return str;
      };



      const traverseChildren = (element, func, depth) => {
        var length = element.children.length;
        for (var i = 0; i < length; i++) {
          traverseChildren(element.children[i], func, depth + 1);
        }
        func(element, depth);
      };
      const makeContentVisible = (element, visible) => {
        var img = element.previousElementSibling.querySelectorAll('img')[0];
        if (visible) {
          element.style.display = '';
          img.setAttribute('src', options.imgExpanded);
          img.setAttribute('data-status', 1);
        } else {
          element.style.display = 'none';
          img.setAttribute('src', options.imgCollapsed);
          img.setAttribute('data-status', 0);
        }
      };
      const ProcessObject = (obj, indent, addComma, isArray, isPropertyContent) => {

        var html = "";
        var comma = (addComma) ? "<span class='jf-Comma'>,</span> " : "";
        var type = typeof obj;
        var clpsHtml = "";
        var prop;
        if (isArrayCheck(obj)) {

          if (obj.length == 0) {
            html += getRow(indent, "<span class='jf-ArrayBrace'>[ ]</span>" + comma, isPropertyContent);
          } else {
            clpsHtml = options.isCollapsible ? "<span><img class='imgToggle' data-status='1' src='" + options.imgExpanded + "'/></span><span class='jf-collapsible'>" : "";
            html += getRow(indent, "<span class='jf-ArrayBrace'>[</span>" + clpsHtml, isPropertyContent);
            for (var i = 0; i < obj.length; i++) {
              html += ProcessObject(obj[i], indent + 1, i < (obj.length - 1), true, false);
            }
            clpsHtml = options.isCollapsible ? "</span>" : "";
            html += getRow(indent, clpsHtml + "<span class='jf-ArrayBrace'>]</span>" + comma);
          }

        } else if (type == 'object') {
          if (obj == null) {
            html += formatLiteral("null", "", comma, indent, isArray, "Null");
          } else {
            var numProps = 0;
            for (prop in obj) numProps++;
            if (numProps == 0) {
              html += getRow(indent, "<span class='jf-ObjectBrace'>{ }</span>" + comma, isPropertyContent);
            }
            else {
              clpsHtml = options.isCollapsible ? "<span><img class='imgToggle' data-status='1' src='" + options.imgExpanded + "'/></span><span class='jf-collapsible'>" : "";
              html += getRow(indent, "<span class='jf-ObjectBrace'>{</span>" + clpsHtml, isPropertyContent);
              var j = 0;
              for (prop in obj) {
                var quote = options.quoteKeys ? "\"" : "";
                html += getRow(indent + 1, "<span class='jf-PropertyName' contenteditable='true' >" + quote + prop + quote + "</span>: " + ProcessObject(obj[prop], indent + 1, ++j < numProps, false, true));
              }
              clpsHtml = options.isCollapsible ? "</span>" : "";
              html += getRow(indent, clpsHtml + "<span class='jf-ObjectBrace'>}</span>" + comma);
            }
          }
        } else if (type == 'number') {
          html += formatLiteral(obj, "", comma, indent, isArray, "Number");
        } else if (type == 'boolean') {
          html += formatLiteral(obj, "", comma, indent, isArray, "Boolean");
        } else if (type == 'undefined') {
          html += formatLiteral("undefined", "", comma, indent, isArray, "Null");
        } else {
          html += formatLiteral(obj.toString().split("\\").join("\\\\").split('"').join('\\"'), "\"", comma, indent, isArray, "String");
        }
        return html;
      };

      const GetenClassCode = (obj, name, showsummary) => {
        var clas = "<div class='' style=' font-size: 13px;'>&nbsp;public class " + name + "</div>";
        clas += "<div class='' style=' font-size: 15px;'>&nbsp;{</div>"
        try {
          if (obj != null) {
            var count = 0;
            for (var n in obj) {
              var v = obj[n];
              clas += GenComment(v, showsummary, count)
              clas += "<div class='ec_p '><span class='ec_r'> <span class='ec_f'> public  &nbsp; </span> <span class='ec_f'>" + GenTypeByProp(n, v, showsummary) + "</span>  &nbsp;   " + n + " &nbsp; { <span class='ec_f'>get</span>; <span class='ec_f'>set</span>; }</span></div>";
              count++;
            }
          }
        } catch (e) {
          clas += e;
        }
        clas += "<div >&nbsp;}</div>";
        options.allClass.push(clas);
        return options.allClass.join("");
      };


      const GenComment = (val, showsummary, count) => {
        //var commm = typeof (val) == "string" && /.*[\u4e00-\u9fa5]+.*$/.test(val) ? val : "";
        //return "/// &#60;summary&#62;<br/>&nbsp;&nbsp;/// " + commm + "<br/>&nbsp;&nbsp;/// &#60;/summary&#62;<br/>";
        var html = "";
        if (count != 0) {
          html += "<div class=''><span class='ec_r'>&nbsp;</span></div>";
        }
        if (showsummary) {
          html += "<div class='ec_p ec_summary' ><span class='ec_r'>///summary</span></div>";
          html += "<div class='ec_p ec_summary' ><span class='ec_r'>///</span></div>";
          html += "<div class='ec_p ec_summary' ><span class='ec_r'>///summary</span></div>";
        }
        return html;
      };

      const GenTypeByProp = (name, val, showsummary) => {
        switch (Object.prototype.toString.apply(val)) {
          case "[object Number]":
            {
              return val.toString().indexOf(".") > -1 ? "double" : "int";
            }
          case "[object Date]":
            {
              return "DateTime";
            }
          case "[object Object]":
            {
              name = name.substring(0, 1).toUpperCase() + name.substring(1);
              GetenClassCode(val, name, showsummary);
              return name;
            }
          case "[object Array]":
            {
              return "List &#60;" + GenTypeByProp(name + "Item", val[0]) + " &#62;";
            }
          default:
            {
              return "string";
            }
        }
      }
      //给展示的div赋值
      const SetresultJson = (html) => {
        try {

          document.getElementById('Canvas').innerHTML = "<span  style='font-size:15px' >" + html + "</span>";
        } catch (e) {
          document.getElementById('Canvas').innerHTML = "<span  style='font-size:12px;color:#F3592A' >" + e + "</span>";
        }
      };
      return {
        content, options, dialog, showSummary, RenderJosnHtml, changeContent,open,
        doFormat, collapseAll, collapseLevel, Compress, Vary, RemoveVary, SelectAllClicked, GenerateEntity
      };

    }

  }
</script>

<style scoped>
  @import url("~@/assets/jsonFormater/jsonFormater.css");
</style>